<?php

class XMLStream {
    
	private
		$position = 0,
		$sXML = '';
		
    public function stream_open($path, $mode, $options, &$opened_path) {
    	if (mb_substr (trim($path,'/'), 0, 7) == 'xmodule') {
    		return $this->buildModuleXML (mb_substr ($path, 10));
    	} elseif (mb_substr (trim($path,'/'), 0, 7) == 'xobject') {
    		return $this->buildObjectXML (mb_substr ($path, 10));
    	}
    	
    	return false;
    }
    
    public function stream_read($count) {
        $ret = substr ($this->sXML, $this->position, $count);
        $this->position += strlen($ret);
        
        return $ret;
    }
    
    public function stream_write($data){
       return false;
    }
    
    public function stream_tell() {
        return $this->position;
    }
    
    public function stream_eof() {
        return $this->position >= mb_strlen ($this->sXML);
    }
    
    public function stream_seek($offset, $whence) {
        $l = mb_strlen ($this->sXML);
        
        switch ($whence) {
            case SEEK_SET: $newPos = $offset; break;
            case SEEK_CUR: $newPos = $this->position + $offset; break;
            case SEEK_END: $newPos = $l + $offset; break;
            default: return false;
        }
        
        $ret = ($newPos >=0 && $newPos <= $l);
        
        if ($ret) {
        	$this->position = $newPos;
        }
        
        return $ret;
    }
    
    public function url_stat ($path, $flags) {
    	return array ();
    }
    
    private function buildObjectXML ($request) {
    	$aParts = explode ('/', $request);

    	if (empty ($aParts[0]) || empty ($aParts[1])) {
    		return false;
    	}
    	
    	if (is_numeric ($aParts[0])) {
    		$oType = TypesController::getInstance()->getTypeById ($aParts[0]);
		} else {
			$oType = TypesController::getInstance()->getTypeByName ($aParts[0]);
		}
		
		if (!$oType) {
			$xml = new DOMDocument;
	    	$dataNode = $xml->createElement ('data');
	    	$xml->appendChild ($dataNode);
	    	
	    	$this->sXML = $xml->saveXML ();
	    	
	    	return true;
		}
		
		$xml = new DOMDocument;
    	
    	$dataNode = $xml->createElement ('data');
    	if ($object = ObjectsController::getInstance()->getObject ($oType, $aParts[1])) {
    		$dataNode->appendChild ($object->__toXML ($xml));
    	}
    	$xml->appendChild ($dataNode);
    	
    	$this->sXML = $xml->saveXML ();
	    	
	   return true;
    }
    
    private function buildModuleXML ($request) {
    	
    	// Пошел гемор, чтобы не разбивать строку по слешам, а то они могут идти при параметрах
    	
    	$posSlash = strpos($request, '/');
    	if ($posSlash === false || $posSlash == 0) {
    		return false;
    	}
    	$module = mb_substr ($request, 0, (int) strpos($request, '/'));
    	    	
    	$withoutModule = mb_substr ($request, $posSlash+1);
   	
    	$posSlash = strpos($withoutModule, '/');
    	if ($posSlash !== false) {
    		$method = mb_substr ($withoutModule, 0, (int) strpos($withoutModule, '/'));
    	} elseif ($withoutModule != '') {
    		$method = $withoutModule;
    	} else {
    		return false;
    	}
    	
	   	$sParams = mb_substr ($withoutModule, mb_strlen($method) + (mb_strlen($method) < mb_strlen ($withoutModule) ? 1 : 0));
        $aParams =  $sParams == '' ? array() : explode (';', $sParams);
              
       	$oResponse = CMSController::getInstance()->runModuleMethod ($module, $method, $aParams, true);
       	
       	$XMLTranslator = new XMLTranslator;
       	$this->sXML = $XMLTranslator->buildPageResponse($oResponse)->saveXML();
        
        return true;
    }
    
    
}